#include "app_mqtt.h"
#include "MQTTClient.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "log/log.h"

// 定义MQTT客户端对象
static MQTTClient client;
// 初始化MQTT连接选项结构体
static MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;

// 静态初始化一个MQTT消息结构体，用于后续发布消息
static MQTTClient_message pubmsg = MQTTClient_message_initializer;

// 定义一个MQTT接收回调函数指针，用于外部注册
static int (*recv_callback)(char *json) = NULL;

/**
 * @brief 消息发送确认回调函数
 *
 * 当消息成功发送到MQTT服务器时，该函数会被调用。
 *
 * @param context 回调上下文，一般为NULL
 * @param dt 消息发送的令牌，用于唯一标识一条消息
 */
static void delivered(void *context, MQTTClient_deliveryToken dt)
{
    // 打印消息发送确认信息，包含令牌值
    log_debug("MQTT发送消息完成");
}

/**
 * @brief 消息到达回调函数
 *
 * 当客户端接收到订阅主题的消息时，该函数会被调用。
 *
 * @param context 回调上下文，一般为NULL
 * @param topicName 消息所在的主题名称
 * @param topicLen 主题名称的长度
 * @param message 接收到的MQTT消息结构体指针
 * @return int 固定返回1，表示消息处理完成
 */
static int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    // 0：失败  1：成功
    int result = 0;     

    if (recv_callback != NULL)
    {
        // 调用外部注册的回调函数处理消息
        result = recv_callback((char *)message->payload) == 0 ? 1 : 0;
    }
    

    // 打印消息到达提示
    printf("Message arrived\n");
    // 打印消息所在的主题名称
    printf("   topic: %s\n", topicName);
    // 打印接收到的消息内容
    printf("  message: %.*s\n", message->payloadlen, (char *)message->payload);
    // 释放消息结构体占用的内存
    MQTTClient_freeMessage(&message);
    // 释放主题名称占用的内存
    MQTTClient_free(topicName);
    // 返回1表示消息处理完成
    return result;
}

/**
 * @brief 连接丢失回调函数
 *
 * 当客户端与MQTT服务器的连接断开时，该函数会被调用。
 *
 * @param context 回调上下文，一般为NULL
 * @param cause 连接丢失的原因描述
 */
static void connlost(void *context, char *cause)
{
    // 打印连接丢失提示
    log_debug("MQTT连接丢失");
    // 打印连接丢失的原因
    log_debug("MQTT连接丢失原因: %s", cause);
}

/**
 * @brief 初始化mqtt
 *
 * @return int 0: 成功 -1: 失败
 */
int app_mqtt_init(void)
{
    // 1. 创建MQTT客户端
    if (MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL) != MQTTCLIENT_SUCCESS)
    {
        log_debug("MQTT客户端创建失败");
        return -1;
    }
    // 2. 设置回调
    if (MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered) != MQTTCLIENT_SUCCESS)
    {
        log_debug("MQTT客户端回调函数设置失败");
        // 失败之后销毁客户端
        MQTTClient_destroy(&client);
        return -1;
    }

    // 3. 连接MQTT服务器
    if (MQTTClient_connect(client, &conn_opts) != MQTTCLIENT_SUCCESS)
    {
        log_debug("MQTT客户端连接失败");
        MQTTClient_destroy(&client);
        return -1;
    }

    // 4. 订阅主题
    if (MQTTClient_subscribe(client, TOPIC_PULL, QOS) != MQTTCLIENT_SUCCESS)
    {
        log_debug("MQTT客户端订阅主题失败");
        MQTTClient_disconnect(client, TIMEOUT);
        MQTTClient_destroy(&client);
        return -1;
    }

    return 0;
}

/**
 * @brief 关闭mqtt
 *
 */
void app_mqtt_close(void)
{
    MQTTClient_unsubscribe(client,TOPIC_PULL);
    MQTTClient_disconnect(client, TIMEOUT);
    MQTTClient_destroy(&client);
}

/**
 * @brief 发送mqtt消息
 *
 * @param json json字符串
 * @return int 0: 成功 -1: 失败
 */
int app_mqtt_send(char *json)
{
    // 1. 填充消息结构体
    pubmsg.payload = json;
    pubmsg.payloadlen = strlen(json);
    pubmsg.qos = QOS;
    pubmsg.retained = 0;

    // 2. 发布消息
    if (MQTTClient_publishMessage(client, TOPIC_PUSH, &pubmsg, NULL) != MQTTCLIENT_SUCCESS)
    {
        log_debug("MQTT客户端发布消息失败");
        return -1;
    }
    log_debug("MQTT客户端发布消息成功: %s", json);

    return 0;
}

/**
 * @brief 注册mqtt接收回调函数
 *
 * @param callback 回调函数
 */
void app_mqtt_registerRecvCallback(int (*callback)(char *json))
{
    recv_callback = callback;
}
